package me.zhengjie.pool.ipproxy;


import com.alibaba.fastjson.JSON;
import me.zhengjie.pool.excutor.CustomExecutorService;
import me.zhengjie.pool.ipproxy.domain.IPInfo;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;

/**
 * @Date 创建时间： 2021-01-14 10:21
 * @Author 作者姓名: WuNengDeShiXiong
 * @Version 1.0
 * @Copyright Copyright by
 * @Direction 类说明       定时取一个免费的源，然后对免费的源获取的IP做数据检查
 *                        多线程获取-然后做数据检测
 */
@Component
@Lazy(value = false)
@EnableScheduling
public class UpdateIpSource1 {

    private final static Logger logger = LoggerFactory.getLogger( UpdateIpSource1.class ) ;

    @Autowired
    private RedisTemplate redisTemplate;

    /***
     * 获取可用的IP代理池，10分钟运行一次
     */
    //@Scheduled(cron = "0 */10 * * * ?")
    public void ips() {
//        String prefix = "http://www.66ip.cn/" ;
//        String suxfix = ".html" ;
//        StringBuilder url = null ;
//        //只取前5页的有效数据
//        for(int i=2 ;i<20 ;i++){
//            url = new StringBuilder( prefix ).append( i ).append( suxfix ) ;
//            parseUrl( url.toString() ) ;
//        }


        String newURL = "http://www.66ip.cn/nmtq.php?getnum=300&isp=0&anonymoustype=0&start=&ports=&export=&ipaddress=&area=1&proxytype=2&api=66ip";
        parseUrl(newURL);
    }

    /****
     * 解析指定地址，然后从地址内获取IP、端口；
     * @param url
     */
    public void parseUrl( String url ){
        try {
            //Document document = Jsoup.connect( "http://www.66ip.cn/areaindex_1/1.html" ).timeout(3000).get();
//            Document document = Jsoup.connect( url ).timeout(3000).get();
//            Elements tags = document.select("table > tbody > tr");
//            for (Element element : tags) {
//                //取得ip地址节点、端口号节点
//                Elements tdChilds = element.select("td");
//                logger.info( " 准备验证数据 {}    ------source1------" , tdChilds.text() );
//                IPInfo ipInfo = new IPInfo( tdChilds ) ;
//                ipInfo.setSource("1");
//                redisHandler( ipInfo ) ;
//            }



            Document document = Jsoup.connect( url ).timeout(3000).get();
            Elements tags = document.select("body");
            for (Element element : tags) {
                for (Node node : element.childNodes()) {
                    //取得ip地址节点、端口号节点
                    //if (node.baseUri())
                    String nodeStr = node.toString();
                    if (StringUtils.isNotBlank(nodeStr) && nodeStr.contains(":")) {
                        logger.info(" 准备验证数据 {}    ------source1------", nodeStr);
                        String[] arr = nodeStr.trim().split(":");
                        IPInfo ipInfo = new IPInfo();
                        ipInfo.setIp(arr[0]);
                        ipInfo.setPort(arr[1]);
                        redisHandler(ipInfo);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*****
     * 验证读取到的IP地址是否有效，并且写入到Redis服务
     * @param ipInfo
     */
    public void redisHandler( IPInfo ipInfo ){
        //第一步检测数据有效性，且只有有效数据才做数据检测
        if ( ipInfo != null && StringUtils.isNotBlank( ipInfo.getIp() ) && StringUtils.isNotBlank( ipInfo.getPort() ) ) {
            try {
                Integer.parseInt(ipInfo.getPort() ) ;
            }catch (Exception e){
                logger.info("端口号为非数字，丢弃请求.................------source1------");
                return ;
            }
            //第二步 采用多线程对IP端口做代理检测
            CustomExecutorService.execute(new Thread(){
                @Override
                public void run() {
                    Boolean useLess = IpInvalidUtils.useless( ipInfo.getIp() , Integer.parseInt(ipInfo.getPort() )) ;
                    if ( ! useLess ) {
                        String ipInfoJson = JSON.toJSONString( ipInfo ) ;
                        //将有效的数据移动到最左边，第一位
                        List<String> range = redisTemplate.opsForList().range("ip", 0, -1 );
                        if ( ! range.contains( ipInfoJson ) ) {
                            logger.info( " {} 有效，开始-存进redis {}    ------source1------" ,  ipInfoJson );
                            if (redisTemplate.opsForList().size("ip") > 1000) {
                                redisTemplate.opsForList().rightPopAndLeftPush("ip", ipInfoJson);
                            }else{
                                redisTemplate.opsForList().leftPush("ip", ipInfoJson );
                            }
                        }
                    }
                }
            }) ;
        }
    }

    public static void main(String[] args){
        UpdateIpSource1 u = new UpdateIpSource1();
        u.ips();
    }
}
